using System;
using GoblinXNA;
using GoblinXNA.Graphics;
using GoblinXNA.Graphics.Geometry;
using GoblinXNA.SceneGraph;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Color = Microsoft.Xna.Framework.Color;

namespace SplashOn_PhoneLib
{
    public class SplashOn_Wayfinding
    {                
        private const float BUFFER_VALUE = 5;
        private const float CLOSURE_VALUE = 30;

        public bool isWayfindingOn = false;
        public bool isWayfindingViewOn = false;
        public bool isWayfindingViewTransitionToMain = false;

        public TransformNode wayfindingTransParentNode = null;

        public TransformNode wayfindingTransNode = null;
        private GeometryNode objectForWayfindingTransNode = null;
        private Vector3 to = Vector3.Zero;        
        public RenderTarget2D wayfindingRenderTarget;
        public Rectangle wayfindingRenderTargetRect;
        public CameraNode wayfindingCameraNode = null;

        public GeometryNode[] trailObject = new GeometryNode[2];
        public TransformNode[] trailObjectTrans = new TransformNode[2];
        private Vector3[] trailObjectVector = new Vector3[3];

        public SplashOn_Wayfinding(Viewport viewport, Scene scene)
        {
            InitializeWayfinding(viewport, scene);
        }

        private void InitializeWayfinding(Viewport viewport, Scene scene)
        {
            PresentationParameters pp = State.Device.PresentationParameters;
            wayfindingRenderTarget = new RenderTarget2D(State.Device, viewport.Width, viewport.Height, false,
                SurfaceFormat.Color, pp.DepthStencilFormat);
            wayfindingRenderTargetRect = new Rectangle(0, -viewport.Height, viewport.Width, viewport.Height);

            Camera wayfindingCamera = new Camera();
            wayfindingCamera.Translation = new Vector3(0, 0, 275);            
            wayfindingCamera.FieldOfViewY = MathHelper.ToRadians(60);
            wayfindingCamera.ZNearPlane = 1;
            wayfindingCamera.ZFarPlane = 2000;

            wayfindingCameraNode = new CameraNode(wayfindingCamera);
            scene.RootNode.AddChild(wayfindingCameraNode);
        }

        public void setTarget(float targetX, float targetY)
        {
            isWayfindingOn = true;
            to = new Vector3(targetX, targetY, AppConstants.DEFAULT_Z_VALUE);
            objectForWayfindingTransNode = new GeometryNode("objectForWayfindingTransNode")
            {
                Model = new Cylinder(5f, 0.2f, 30, 5),//new Pyramid(20f, 40f, 20f),
                Material = new Material()
                {
                    Diffuse = Color.Orange.ToVector4(),
                    Specular = Color.White.ToVector4(),
                    SpecularPower = 20
                }

            };
            
            trailObject[0] = new GeometryNode("trail1")
            {
                Model = new Cylinder(5f, 0.2f, 25, 5),//new Pyramid(20f, 40f, 20f),
                Material = new Material()
                {
                    Diffuse = new Vector4(Color.Orange.ToVector3(), 0.7f),
                    Specular = Color.White.ToVector4(),

                }
            };
            trailObject[1] = new GeometryNode("trail2")
            {
                Model = new Cylinder(5f, 0.2f, 20, 5),//new Pyramid(20f, 40f, 20f),
                Material = new Material()
                {
                    Diffuse = new Vector4(Color.Orange.ToVector3(), 0.4f),
                    Specular = Color.White.ToVector4(),

                }
            };

            wayfindingTransNode = new TransformNode();
            wayfindingTransNode.AddChild(objectForWayfindingTransNode);
            trailObjectTrans[0] = new TransformNode();
            trailObjectTrans[0].Translation = Vector3.Zero;
            trailObjectTrans[0].AddChild(trailObject[0]);
            trailObjectTrans[1] = new TransformNode();
            trailObjectTrans[1].Translation = Vector3.Zero;
            trailObjectTrans[1].AddChild(trailObject[1]);

            wayfindingTransParentNode = new TransformNode("wayfindingTransParentNode");
            wayfindingTransParentNode.AddChild(wayfindingTransNode);
            wayfindingTransParentNode.AddChild(trailObjectTrans[0]);
            wayfindingTransParentNode.AddChild(trailObjectTrans[1]);

            GeometryNode objectForTargetPointTransNode = new GeometryNode("objectForTargetPointTransNode")
            {
                Model = new Cylinder(5, 5, 25, 8),
                Material = new Material()
                {
                    Diffuse = Color.Red.ToVector4(),
                    Ambient = Color.Red.ToVector4(),
                    Specular = Color.Red.ToVector4(),
                    SpecularPower = 20
                }
            };
            TransformNode targetPointTransNode = new TransformNode("targetPointTransNode")
            {
                Translation = new Vector3(targetX, targetY, AppConstants.DEFAULT_Z_VALUE),
                Rotation = Quaternion.CreateFromAxisAngle(Vector3.UnitX, MathHelper.ToRadians(90))
            };
            targetPointTransNode.AddChild(objectForTargetPointTransNode);

            wayfindingTransParentNode.AddChild(targetPointTransNode);
        }

        public void setTarget(Vector2 target) 
        {
            setTarget(target.X, target.Y);
        }

        public void setTarget(Vector3 target)
        {
            setTarget(target.X, target.Y);
        }
        
        private void UpdateTranslation(TransformNode trailNode, int value)
        {
            trailNode.Rotation = wayfindingTransNode.Rotation;

            float valueY = (wayfindingTransNode.WorldTransformation.Up.Y * value + wayfindingTransNode.Translation.Y);
            float valueX = (wayfindingTransNode.WorldTransformation.Up.X * value + wayfindingTransNode.Translation.X);

            trailNode.Translation = new Vector3(valueX, valueY, 5);

        }

        public bool update(Vector3 from)
        {
            wayfindingTransNode.Translation = from;
            float angleTowardsTarget = CalculationHelper.CalculateAngleDegreesFromUnitY(from, to);           
            wayfindingTransNode.Rotation = Quaternion.CreateFromAxisAngle(-Vector3.UnitZ, 
                    MathHelper.ToRadians(angleTowardsTarget));

            if (Math.Abs(to.X - trailObjectTrans[1].Translation.X) < CLOSURE_VALUE
                && Math.Abs(to.Y - trailObjectTrans[1].Translation.Y) < CLOSURE_VALUE)
            {
                UpdateTranslation(trailObjectTrans[0], 15);
                UpdateTranslation(trailObjectTrans[1], 20);
            }
            else
            {
                UpdateTranslation(trailObjectTrans[0], 20);
                UpdateTranslation(trailObjectTrans[1], 30);

            }

            if (Math.Abs(to.X - from.X) < CLOSURE_VALUE && Math.Abs(to.Y - from.Y) < CLOSURE_VALUE)
            {
                float coneHeight = (Math.Abs(to.X - from.X) > Math.Abs(to.Y - from.Y)) ? Math.Abs(to.X - from.X) : Math.Abs(to.Y - from.Y);
                objectForWayfindingTransNode.Model = new Cylinder(5f, 0.2f, coneHeight, 5);
                trailObjectTrans[0].Enabled = false;
                trailObjectTrans[1].Enabled = false;

            }
            else
            {
                trailObjectTrans[0].Enabled = true;
                trailObjectTrans[1].Enabled = true;
            }
                       
            if (Math.Abs(to.X - from.X) < BUFFER_VALUE && Math.Abs(to.Y - from.Y) < BUFFER_VALUE)
                return true;
            return false;
        }

        public void updateWayfindingView(Scene scene, TransformNode groundNode, Viewport viewport, TimeSpan elapsedTime)
        {
            scene.SceneRenderTarget = wayfindingRenderTarget;
            scene.BackgroundColor = Color.CornflowerBlue;
            scene.BackgroundBound = wayfindingRenderTargetRect;
            scene.CameraNode = wayfindingCameraNode;
            scene.BackgroundTexture = null;            
            scene.Draw(elapsedTime, false);
            wayfindingRenderTargetRect.X += viewport.X;
            DebugHelper.w("wayfindingRenderTargetRect.Y=" + wayfindingRenderTargetRect.Y);
            if (isWayfindingViewTransitionToMain)
            {
                if (wayfindingRenderTargetRect.Y != -480)
                    wayfindingRenderTargetRect.Y -= 40;
                else
                {
                    isWayfindingViewTransitionToMain = false;
                    isWayfindingViewOn = false;
                }
            }
            else if (wayfindingRenderTargetRect.Y != 0)
                wayfindingRenderTargetRect.Y += 40;
            State.Device.SetRenderTarget(null);
            State.Device.Clear(Color.Black);            
            State.SharedSpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Opaque);
            State.SharedSpriteBatch.Draw(wayfindingRenderTarget, wayfindingRenderTargetRect, Color.White);
            State.SharedSpriteBatch.End();

            wayfindingRenderTargetRect.X -= viewport.X;
        }

        public void dispose()
        {
            wayfindingTransNode = null;
            to = Vector3.Zero;
            objectForWayfindingTransNode = null;            
        }

    }
}
